package com.Cfeng.XiaohuanChat.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;

import java.time.Duration;

/**
 * @author Cfeng
 * @date 2022/8/21
 */

@Configuration
@EnableCaching //在配置类中加入该注解，代表启用缓存功能【缓存就是局部性原理】
public class RedisConfigure { //改名是因为IDEA会搜索所有的module，为了避免一些潜在错误
    //将yaml中的属性注入
    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.database}")
    private Integer database;
    @Value("${spring.redis.port}")
    private Integer port;
    @Value("${spring.redis.password}")
    private String password;

    @Primary //标记优先级最高，当byType注入的时候优先
    @Bean(name = "jedisPoolConfig")
    @ConfigurationProperties(prefix = "spring.redis.jedis.pool") //将其中pool下面的属性当作一个对象注入给pool
    public JedisPoolConfig jedisPoolConfig() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxWait(Duration.ofSeconds(10));
        return jedisPoolConfig;
    }

    //使用jedis客户端
    @Bean
    //上面的bean拿下来使用
    public RedisConnectionFactory redisConnectionFactory(JedisPoolConfig jedisPoolConfig) {
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(host, port);
        redisStandaloneConfiguration.setDatabase(database);
        //必须设置密码不然不安全
        redisStandaloneConfiguration.setPassword(password);
        //jedis客户端配置，创建poolConfig，这里要加上cast
        JedisClientConfiguration.JedisPoolingClientConfigurationBuilder jedisPoolClientBuilder = (JedisClientConfiguration.JedisPoolingClientConfigurationBuilder) JedisClientConfiguration.builder();
        //使用poolConfig装载pool对象
        jedisPoolClientBuilder.poolConfig(jedisPoolConfig);
        JedisClientConfiguration jedisClientConfiguration = jedisPoolClientBuilder.build();
        //不仅仅配置port等，还要将配置的jedisPool加入
        return new JedisConnectionFactory(redisStandaloneConfiguration, jedisClientConfiguration);
    }

    //需要使用的参数会自动注入容器中的对象,其他的和之前的相同
    @Primary
    @Bean(name = "redisTemplate")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        //设置客户端类型
        template.setConnectionFactory(redisConnectionFactory);
        //序列化器
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        template.setKeySerializer(stringRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
        //设置value的序列化器为Json，JDK可读性差
        Jackson2JsonRedisSerializer redisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        template.setValueSerializer(redisSerializer);
        template.setHashValueSerializer(redisSerializer);
        //设置默认
        template.afterPropertiesSet();
        return template;
    }
}
